/*******************************************************************************
* Copyright 2011 iovation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.javadrop;
import java.io.File;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.LinkedList;
import java.util.List;
import javax.management.IntrospectionException;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.javadrop.packaging.PackagerStrategy;
import org.javadrop.runner.RunnerStrategy;
/**
* This goal combines one or more 'runner strategies' with one or more 'packager
* strategies' together to produce an artifact that can be installed.
*
* This plugin is intended to keep the configuration in a pom to a minimum. The
* various strategies could get fairly complex in their processing.
*
* @goal javadrop
* @phase install
* @requiresDependencyResolution runtime
*/
public class JavadropMojo extends AbstractMojo {
/** @parameter default-value="${project}" */
protected MavenProject mavenProject;
/**
* Defines the runners that may be packaged up to bundle the software
*
* @parameter
* @required
*/
private List<RunnerDefinition> runnerDefinitions;
/**
* Defines the packagers that are used to build the software distribution archive.
*
* @parameter
* @required
*/
private List<PackagerDefinition> packagerDefinitions;
/**
* Runner strategies. Once the pom has been configured, these are the actual functionality that does the work
* for the defined runners.
*/
private List<RunnerStrategy> runnerStrategies = new LinkedList<RunnerStrategy>();
/**
* Packager strategies. The actual packager functionality is found here.
*/
private List<PackagerStrategy> packagerStrategies = new LinkedList<PackagerStrategy>();
public JavadropMojo() {
}
/**
* Location of the output directory for the template results.
*
* @parameter expression="${project.build.directory}"
* @required
*/
private File workingDirectory;
public void setWorkingDirectory(File workingDirectory) {
this.workingDirectory = workingDirectory;
}
/**
* Location of the output directory for the working files.
*
* @parameter expression="${project.build.directory}"
* @required
*/
private File packageDirectory;
public void setPackageDirectory(File packageDirectory) {
this.packageDirectory = packageDirectory;
}
/*
* (non-Javadoc)
*
* @see org.apache.maven.plugin.AbstractMojo#execute()
*/
public void execute() throws MojoExecutionException {
getLog().info("Javadrop Mojo processing started...");
try {
if ((mavenProject != null)
&& (mavenProject.getCompileClasspathElements() != null)) {
getLog().info("Class augmented with project.");
for (int index = 0; index < mavenProject
.getCompileClasspathElements().size(); index++) {
String path = (String) mavenProject
.getCompileClasspathElements().get(index);
URL cpUrl = new File(path).toURL();
addURLToSystemClassLoader(cpUrl);
}
}
initStrategies();
} catch (MalformedURLException e) {
getLog().warn("Can't add compile classpath elements to mojo!", e);
} catch (DependencyResolutionRequiredException e) {
getLog().warn("Can't add compile classpath elements to mojo!", e);
} catch (IntrospectionException e) {
getLog().warn("Can't add compile classpath elements to mojo!", e);
} catch (ClassNotFoundException e) {
getLog().warn(e);
} catch (InstantiationException e) {
getLog().warn(e);
} catch (IllegalAccessException e) {
getLog().warn(e);
}
// Process runner scripts in the context of a packager.
TemplateProcessor processor = new VelocityTemplateProcessorImpl(
getLog());
for (PackagerStrategy packager : packagerStrategies) {
for (RunnerStrategy runner : runnerStrategies) {
// Convert scripts
packager.processTemplates(runner, processor, workingDirectory);
// Do mappings, renames, whatever in the runner.
packager.postProcessArtifacts(runner, workingDirectory);
}
packager.createPackage(packageDirectory, workingDirectory,
filteredRunnerStrats(packager, runnerStrategies), getLog());
// packager.createPackage(packageDirectory, workingDirectory,
// runnerStrategies, getLog());
}
getLog().info("Javadrop complete.");
}
private List<RunnerStrategy> filteredRunnerStrats(PackagerStrategy packagerStrat, List<RunnerStrategy> runnerStrats) {
List<String> excludedRunners = packagerStrat.getPackagerDefinition().getExcludedRunners();
LinkedList<RunnerStrategy> filteredStrats = new LinkedList<RunnerStrategy>();
for (RunnerStrategy runStrat : runnerStrats) {
if (runStrat.getRunnerDefinition().getRunnerName() == null ||
(excludedRunners.contains(runStrat.getRunnerDefinition().getRunnerName()) == false)) {
filteredStrats.add(runStrat);
}
}
return filteredStrats;
}
public void addURLToSystemClassLoader(URL url)
throws IntrospectionException {
URLClassLoader systemClassLoader = (URLClassLoader) ClassLoader
.getSystemClassLoader();
Class classLoaderClass = URLClassLoader.class;
try {
Method method = classLoaderClass.getDeclaredMethod("addURL",
new Class[] { URL.class });
method.setAccessible(true);
method.invoke(systemClassLoader, new Object[] { url });
} catch (Throwable t) {
t.printStackTrace();
throw new IntrospectionException(
"Error when adding url to system ClassLoader ");
}
}
/**
* This creates the actual strategies used to do the work. It maps the parameters
* found in the pom to the code that will be chugging away.
*
* @throws ClassNotFoundException
* If given class name isn't available
* @throws IllegalAccessException
* Problems creating given strategy
* @throws InstantiationException
* Problems creating given strategy
*/
private void initStrategies() throws ClassNotFoundException,
InstantiationException, IllegalAccessException {
ClassLoader classLoader = getClass().getClassLoader();
for (RunnerDefinition runnerDef : runnerDefinitions) {
String runnerClass = runnerDef.getRunnerClass();
Class<?> aClass = classLoader.loadClass(runnerClass);
RunnerStrategy runnerStrat = (RunnerStrategy) aClass.newInstance();
// Apply the mojo's parameters to the strategy so it knows how to
// process templates.
runnerStrat.applyParameters(runnerDef.getRunnerParameters());
runnerStrat.set_log(getLog());
runnerStrat.setRunnerDefinition(runnerDef);
runnerStrategies.add(runnerStrat);
}
for (PackagerDefinition packagerDef : packagerDefinitions) {
String packagerClass = packagerDef.getPackagerClass();
Class<?> aClass = classLoader.loadClass(packagerClass);
PackagerStrategy packagerStrat = (PackagerStrategy) aClass
.newInstance();
// Apply the mojo's parameters to the strategyso it knows how to
// process templates.
packagerStrat.applyParameters(packagerDef.getPackagerParameters());
packagerStrat.set_log(getLog());
packagerStrat.setPackagerDefinition(packagerDef);
packagerStrategies.add(packagerStrat);
}
}
public List<RunnerDefinition> getRunnerDefinitions() {
return runnerDefinitions;
}
/**
* Check the values supplied in the pom to see if they are ok.
*
* @throws MojoExecutionException
*/
// private void validateParameters() throws MojoExecutionException
// {
// // Override default values with what is supplied in the .pom
// mergedVariables.putAll(serviceVariables);
// getLog().info("Scriptgen mojo variables");
// for (Entry<String,String> velVariable : mergedVariables.entrySet()) {
// getLog().info(" Definition: " + velVariable.getKey() + "=" +
// velVariable.getValue());
// }
//
// // Check required variables.
// List<String> missingVars = new LinkedList<String>();
// for (String reqVar : requiredVariables) {
// if (mergedVariables.containsKey(reqVar) == false) {
// missingVars.add(reqVar);
// }
// }
//
// if (missingVars.isEmpty() == false) {
// StringBuilder sb = new StringBuilder();
// boolean first = true;
// for (String missingVar : missingVars) {
// if (!first) sb.append(',');
// else first = false;
// sb.append(missingVar);
// }
// throw new
// MojoExecutionException("Script generation is missing required variables: "
// + sb.toString());
// }
//
// // Apply the variables to the velocity context.
// for (Entry<String,String> contextVar : mergedVariables.entrySet()) {
// velContext.put(contextVar.getKey(), contextVar.getValue());
// }
// }
/**
* Determine the particular service type being targed.
*/
// private void determineStrategy() throws MojoExecutionException
// {
// // Check the serviceType provided.
// if (serviceType == null) {
// throw new
// MojoExecutionException("Missing 'serviceType'. Must be one of ('jetty', 'standalone')");
// }
// if ("jetty".equalsIgnoreCase(serviceType)) {
// serviceStrategy = new JettyStrategy();
// } else if ("standalone".equalsIgnoreCase(serviceType)) {
// serviceStrategy = new MainServiceStrategy();
// }
// if (serviceStrategy == null) {
// throw new
// MojoExecutionException("Invalid 'serviceType'. Must be one of ('jetty', 'standalone')");
// }
// }
}